package logger

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"
)

type RollingFileAppender struct {
	name   string
	output StringWriter
}

type RollingFileStringWriter struct {
	disabled bool
	filename string
	file     *os.File
	pattern  string
	day      int
}

func (w *RollingFileStringWriter) WriteString(time time.Time, name, level, text string) (n int, err error) {
	if w.disabled || w.pattern == "" {
		return 0, nil
	}
	if time.Day() != w.day {
		err := os.Rename(w.file.Name(), w.file.Name()+"."+time.Format("2006-01-02"))
		if err != nil {
			fmt.Errorf("open file error: %v\n", err)
		} else {
			file, err := os.OpenFile(w.filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
			if err != nil {
				fmt.Errorf("open file error: %v\n", err)
			} else {
				oldFile := w.file
				w.file = file
				oldFile.Close()
			}
		}
		w.day = time.Day()
	}
	output := strings.NewReplacer(
		"%d", time.Format(NormalDateTimeMsPattern),
		"%logger", name,
		"%level", level,
		"%msg", text,
		"%n", "\n",
	).Replace(w.pattern)
	return (*w.file).WriteString(output)
}

func NewRollingFileAppender(name, filename, pattern string, rollingPolicy *SizeAndTimeBasedRollingPolicy) *RollingFileAppender {
	err := os.MkdirAll(filepath.Dir(filename), 0755)
	if err != nil {
		fmt.Errorf("can't make directories for new logfile: %s", err)
	}
	file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		fmt.Printf("open file error: %v\n", err)
		return &RollingFileAppender{name: name, output: &RollingFileStringWriter{disabled: true, filename: filename, file: file, pattern: pattern, day: time.Now().Day()}}
	}
	return &RollingFileAppender{name: name, output: &RollingFileStringWriter{disabled: false, filename: filename, file: file, pattern: pattern, day: time.Now().Day()}}
}

func (appender *RollingFileAppender) Name() string {
	return appender.name
}

func (appender *RollingFileAppender) Output() StringWriter {
	return appender.output
}
